%include "boot.inc"
;org 0x7e00
[bits 16]
mov ax,0xb800
mov gs,ax
mov ah,0x03  ;青色
mov ecx,bootloader_tag_end - bootloader_tag
xor ebx,ebx
add ebx,80*1*2 ;第二行
mov esi,bootloader_tag
output_bootloader_tag:
    mov al,[esi]
    mov word[gs:bx],ax
    inc esi
    add ebx,2
    loop output_bootloader_tag
;空描述符
mov dword[GDT_START_ADDRESS+0x00],0x00
mov dword[GDT_START_ADDRESS+0x04],0x00
;创建描述符，数据段，对应0-4GB的线性地址空间
mov dword[GDT_START_ADDRESS+0x08],0x0000ffff	;基地址为0，段界限为0xfffff
mov dword[GDT_START_ADDRESS+0x0c],0x00cf9200	;粒度为4kb，存储器段描述符
;建立保护模式下的堆栈段描述符
mov dword[GDT_START_ADDRESS+0x10],0x00000000	;基地址为0，段界限为0
mov dword[GDT_START_ADDRESS+0x14],0x00409600	;粒度为1个字节
;建立保护模式下的显存描述符
mov dword[GDT_START_ADDRESS+0x18],0x80007fff	;基地址为0xb8000，段界限0x07fff
mov dword[GDT_START_ADDRESS+0x1c],0x0040920b	;粒度为字节
;创建保护模式下的平坦模式代码段描述符
mov dword[GDT_START_ADDRESS+0x20],0x0000ffff	;基地址为0，段界限为0xfffff
mov dword[GDT_START_ADDRESS+0x24],0x00cf9800	;粒度为4kb，代码段描述符

;初始化描述符表寄存器GDTR
mov word[pgdt],39	;描述符表的界限
lgdt [pgdt]

;打开第21根地址线
in al,0x92		;南桥芯片内的端口
or al,0000_0010B	
out 0x92,al		;打开A20
;设置cr0保护模式开关位
cli			;中断机制尚未工作，禁用中断
mov eax,cr0
or eax,1
mov cr0,eax		;设置PE位
;远跳转进入保护模式
jmp dword CODE_SELECTOR:protect_mode_begin

;16位的描述符选择子：32位偏移
;清流水线，串行化处理器
[bits 32]
protect_mode_begin:
mov eax,DATA_SELECTOR	;加载数据段选择子
mov ds,eax
mov es,eax
mov eax,STACK_SELECTOR
mov ss,eax
mov eax,VIDEO_SELECTOR
mov gs,eax

mov ecx,protect_mode_tag_end - protect_mode_tag
mov ebx,80*2*2		;第三行显示
mov esi,protect_mode_tag
mov ah,0x3
output_protect_mode_tag:
    mov al,[esi]
    mov word[gs:ebx],ax
    add ebx,2
    inc esi
    loop output_protect_mode_tag
;输出标签
mov ecx,string_end - string
mov ebx,(80*10+18)*2
mov esi,string
mov ah,0x5b		;背景红 字体青色
output_string:
    mov al,[esi]
    mov word[gs:ebx],ax
    add ebx,2
    inc esi
    loop output_string
;  start (2,0),xy代表位置行列，v代表速度
print_char:
    call random
    call print
    call random
    call print1
    call delay
    call judge
jmp $ ;死循环

random:
    push eax
    push ecx
    push edx
    mov bx,[seed]
    imul ebx,ebx,19
    add bx,29
    mov [seed],bx
    ;and bl,0x7f	;limit ancii
    ;限制数字
    mov edx,0
    mov eax,0
    mov al,bl
    mov ecx,10
    idiv ecx
    mov bl,dl
    add bl,48		;'0'ancii
    pop edx
    pop ecx
    pop eax
    ret
print:
    push eax
    push ebx
    push ecx
    mov ax,bx
    mov bx,0
    mov cx,0
    mov bl,byte[xy]
    mov cl,byte[xy+1]
    imul bx,bx,80
    add bx,cx		;此处不能使用bl+cl而应该用bx+cx,这是为了防止溢出损失
    imul bx,bx,2
    mov [gs:bx],ax
    pop ecx
    pop ebx
    pop eax
    ret
print1:
    push eax
    push ebx
    push ecx
    mov ax,bx
    mov bx,0
    mov cx,0
    mov bl,byte[xy1]
    mov cl,byte[xy1+1]
    imul bx,bx,80
    add bx,cx		;此处不能使用bl+cl而应该用bx+cx,这是为了防止溢出损失
    imul bx,bx,2
    mov [gs:bx],ax
    pop ecx
    pop ebx
    pop eax
    ret
delay:
    push ecx
    mov ecx,10000000
    delay_loop:
        dec ecx
        jnz delay_loop
    pop ecx
    ret
judge:
    push eax
    mov al,byte[v]
    add byte[xy],al
    mov al,byte[v+1]
    add byte[xy+1],al
    mov al,byte[v1]
    add byte[xy1],al
    mov al,byte[v1+1]
    add byte[xy1+1],al
    pop eax
    cmp byte[xy],24
    je bounce_x
    cmp byte[xy],0
    je bounce_x
    cmp byte[xy+1],79
    je bounce_y
    cmp byte[xy+1],0
  cmpxy1:
    je bounce_y
    cmp byte[xy1],24
    je bounce_x1
    cmp byte[xy1],0
    je bounce_x1
    cmp byte[xy1+1],79
    je bounce_y1
    cmp byte[xy1+1],0
    je bounce_y1
    jmp print_char
bounce_x:
    neg byte[v]
    jmp cmpxy1
bounce_y:
    neg byte[v+1]
    jmp cmpxy1
bounce_x1:
    neg byte[v1]
    jmp print_char
bounce_y1:
    neg byte[v1+1]
    jmp print_char
.data:
pgdt dw 0
        dd GDT_START_ADDRESS
bootloader_tag db 'run bootloader...'
bootloader_tag_end:
protect_mode_tag db 'You enter protect mode!'
protect_mode_tag_end:
string db "22336271 ysj,I'm your operating system!Thank you:)"
string_end:
xy db 2,0
v  db 1,1
xy1 db 22,79
v1 db -1,-1
seed dw 65521		;随机数种子
